﻿using System;
using System.Collections.Generic;
using System.Linq;

using MvcCms.Data.Pagination;
using MvcCms.Service.Cache;
using MvcCmsProjectTracker.Data;
using MvcCms.Data;
using MvcCms.Service.Logging;
using MvcCms.Service.Code;
using MvcCms.Service.Code.DataTables;
using Microsoft.Practices.ServiceLocation;
using MvcCms.Service;
using MvcCms.Service.Models;
using MvcCms.Service.Code.Email;
using MvcCmsProjectTracker.Service.Entities;

namespace MvcCmsProjectTracker.Service
{
    public class BugService : IBugService
    {
        #region Constructors

        private readonly IBugRepository _repository;
        private readonly ICacheService _cacheService;
        public BugService(IBugRepository repository, ICacheService cacheService)
        {
            _repository = repository;
            _cacheService = cacheService;
        }

        #endregion

        public void Save()
        {
            try
            {
                _repository.Save();
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
            }
        }
        public bool CreateBug(Bug bugToCreate)
        {            
            try
            {
                _repository.CreateBug(bugToCreate);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool EditBug(Bug bugToEdit)
        {
            // Database logic
            try
            {
                _repository.EditBug(bugToEdit);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }

        #region List Methods

        public DtoIssues ListIssues(DataTablesRequest dataTablesRequest, string columnsToReturn)
        {
            var columnNames = columnsToReturn.Split(',');
            var dtoIssues = new DtoIssues();

            var query = _repository.ListIssues(_cacheService.GetCurrentPortal().PortalID).AsQueryable();
            //Get the totalItems/TotalRecords now we need this before filters are applied
            dtoIssues.GetPagination.iTotalRecords = query.Count();

            query = query.SearchForDataTables(dataTablesRequest, columnNames) as IQueryable<DtoTrackerIssue>;
            //Get the totalDisplayRecords after filtering has been applied.
            dtoIssues.GetPagination.iTotalDisplayRecords = query.Count();

            query = DataTablesSort.Sort(dataTablesRequest, query, columnNames) as IQueryable<DtoTrackerIssue>;

            //Pass the number of records after filtering to AsPagination so it doesn't query again for the total 
            //The filtered count is the one it is expecting to calculate TotalPages
            var queryPaginated = query.AsPagination(dataTablesRequest.iCurrentPage, dataTablesRequest.iDisplayLength, dtoIssues.GetPagination.iTotalDisplayRecords);

            var issues = queryPaginated.ToList();
            var records = from i in issues
                          select new DtoIssue
                          {
                              BugID = i.BugID,
                              ProjectID = i.ProjectID,
                              ProjectName = i.ProjectName,
                              CategoryName = i.CategoryName,
                              PriorityName = i.PriorityName,
                              MileStoneName = i.MileStoneName,
                              Title = i.Title,
                              Status = i.Status,
                              CreatorUserName = i.CreatorUserName,
                              Assigned = i.Assigned,
                              DateCreated = i.DateCreated,
                              LastUpdate = i.LastUpdate
                          };
            dtoIssues.AddRange(records);
            return dtoIssues;
        }

        public IQueryable<BugAttachment> GetBugAttachments(int bugID)
        {
            return _repository.GetBugAttachments(bugID);
        }
        public IQueryable<BugComment> GetBugComments(int bugID)
        {
            return _repository.GetBugComments(bugID);
        }
        public IQueryable<BugHistory> GetBugHistories(int bugID)
        {
            return _repository.GetBugHistories(bugID);
        }
        public IQueryable<BugNotification> GetBugNotifications(int bugID)
        {
            return _repository.GetBugNotifications(bugID);
        }
        public IQueryable<Bug> GetBugsByCategory(int projectID, int categoryID)
        {
            return _repository.GetBugsByCategory(projectID, categoryID);
        }
        public IQueryable<Bug> GetBugsByMilestone(int projectID, int milestoneID)
        {
            return _repository.GetBugsByMilestone(projectID, milestoneID);
        }
        public IQueryable<Bug> GetBugsByPriority(int projectID, int priorityID)
        {
            return _repository.GetBugsByPriority(projectID, priorityID);
        }
        public IQueryable<Bug> GetBugsByProject(int projectID)
        {
            return _repository.GetBugsByProject(projectID);
        }
        public IQueryable<Bug> GetBugsByStatus(int projectID, int statusID)
        {
            return _repository.GetBugsByStatus(projectID, statusID);
        }
        public IQueryable<Bug> GetMyBugs(Guid userId)
        {
            return _repository.GetMyBugs(userId);
        }
        #endregion

        #region Get Methods
        public Bug GetBug(int bugID)
        {
            return _repository.GetBug(bugID);
        }
        public BugAttachment GetBugAttachment(int attachmentID)
        {
            return _repository.GetBugAttachment(attachmentID);
        }
        public BugComment GetBugComment(int commentID)
        {
            return _repository.GetBugComment(commentID);
        }
        public BugHistory GetBugHistory(int historyID)
        {
            return _repository.GetBugHistory(historyID);
        }
        public BugNotification GetBugNotification(int notificationID)
        {
            return _repository.GetBugNotification(notificationID);
        }

        #endregion

        #region Add Methods
        public bool AddBug(Bug bug)
        {
            try
            {
                _repository.AddBug(bug);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool AddBugAttachment(BugAttachment attachment)
        {
            try
            {
                _repository.AddBugAttachment(attachment);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool AddBugComment(BugComment comment)
        {
            try
            {
                _repository.AddBugComment(comment);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool AddBugHistory(BugHistory history)
        {
            try
            {
                _repository.AddBugHistory(history);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool AddBugNotification(BugNotification notification)
        {
            try
            {
                _repository.AddBugNotification(notification);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }

        #endregion

        #region Delete Methods
        public bool DeleteBug(Bug bug)
        {
            try
            {
                _repository.DeleteBug(bug);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool DeleteBugAttachment(BugAttachment attachment)
        {
            try
            {
                _repository.DeleteBugAttachment(attachment);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool DeleteBugComment(BugComment comment)
        {
            try
            {
                _repository.DeleteBugComment(comment);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool DeleteBugHistory(BugHistory history)
        {
            try
            {
                _repository.DeleteBugHistory(history);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool DeleteBugNotification(BugNotification notification)
        {
            try
            {
                _repository.DeleteBugNotification(notification);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }

        #endregion

    }
}